Skip to content

aitools: add --output json to install - #6481

Open
rclarey wants to merge 3 commits into
mainfrom
aitools-install-output-json
Open

aitools: add --output json to install#6481
rclarey wants to merge 3 commits into
mainfrom
aitools-install-output-json

Conversation

@rclarey

@rclarey rclarey commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Changes

Add --output json to aitools install. This requires --scope and --agents to avoid needing to prompt users on stdout

Why

Needed for #6482

Tests

Added unit tests

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Approval status: pending

/cmd/aitools/ - needs approval

5 files changed
Suggested: @lennartkats-db
Also eligible: @misha-db, @rugpanov, @parthban-db, @anton-107, @fjakobs, @Shridhad, @atilafassina, @keugenek, @igrekun, @pkosiec, @MarioCadenas, @pffigueiredo, @ditadi, @calvarjorge

/libs/aitools/ - needs approval

Files: libs/aitools/installer/installer.go
Suggested: @lennartkats-db
Also eligible: @misha-db, @rugpanov, @parthban-db, @anton-107, @fjakobs, @Shridhad, @atilafassina, @keugenek, @igrekun, @pkosiec, @MarioCadenas, @pffigueiredo, @ditadi, @calvarjorge

General files (require maintainer)

5 files changed
Based on git history:

  • @simonfaltum -- recent work in cmd/aitools/, libs/aitools/installer/

Any maintainer (@andrewnester, @anton-107, @denik, @pietern, @shreyas-goenka, @simonfaltum, @renaudhartert-db, @janniklasrose, @lennartkats-db, @rugpanov) can approve all areas.
See OWNERS for ownership rules.

@rugpanov rugpanov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated multi-reviewer pass (Isaac, Codex, and Claude reviewers, cross-checked against the code). The feature itself is sound and mirrors aitools list --output json. Inline comments below; a few findings that don't anchor to a changed line:

[nice to have] --path + --output json silently ignores JSON (cmd/aitools/install.go:124) — the --path block returns before the jsonMode check (:138) and render (:197), so install --path DIR --output json does a text dump with exit 0 and no JSON. --skills-only+--path is already rejected at :105; per CLAUDE.md's "reject incompatible inputs early" rule, either reject this combination or honor JSON in the dump path.

[nice to have] Coverage / convention gaps — (1) no .nextchanges/cli/ changelog fragment for this user-visible output mode (the analogous aitools list --output json, #5233, shipped one; not CI-blocking but expected by .agents/rules/changelog.md); (2) only unit tests were added — .agents/rules/testing.md prefers acceptance coverage for user-visible output, and the suite already exists at acceptance/experimental/aitools/skills/install/. An acceptance case would also have caught the stderr finding below, since it runs the real binary through root.Execute.

[nit] Help text (cmd/aitools/install.go:83) — the Long help / "Escape hatches" list doesn't mention --output json or its --scope+--agents requirement, so users hit the error only at runtime.

Comment thread cmd/aitools/install.go Outdated
// also print runErr as a text "Error:" line. Silence cobra's
// error/usage output; the non-zero exit still comes from returning
// runErr.
cmd.SilenceErrors = true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[blocking] SilenceErrors doesn't suppress the Error: line — the JSON contract is broken in production.

This repo's root prints errors itself: cmd/root/root.go:166 does fmt.Fprintf(cmd.ErrOrStderr(), "Error: %s\n", …), gated only on errors.Is(err, ErrAlreadyPrinted) (root already sets SilenceErrors: true at root.go:40, so cobra never prints on its own). So setting SilenceErrors here is a no-op, and a failed install … --output json writes the JSON to stdout and Error: … to stderr.

TestInstallOutputJSON passes only because it calls the leaf cmd.Execute(), which bypasses root.Execute.

Established fix — see cmd/environments/output.go:36-38: after the successful render, return root.ErrAlreadyPrinted on failure (non-zero exit, no text line) instead of relying on SilenceErrors. Requires importing github.com/databricks/cli/cmd/root. Please also add a test that goes through root.Execute so the stderr assertion is meaningful.

Comment thread cmd/aitools/install.go
Comment thread cmd/aitools/install.go Outdated
if jsonMode {
if jerr := renderJSON(cmd.OutOrStdout(), buildInstallOutput(opts.Scope, outcomes, runErr)); jerr != nil {
// Rendering failed, so the JSON the caller parses is broken.
// Report the render error (which also drives the deferred

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] "which also drives the deferred telemetry" is inaccurate — the deferred logInstallEvent fires regardless of the returned error, so returning runErr here doesn't drive telemetry. Worth trimming the parenthetical.

Comment thread cmd/aitools/install_test.go Outdated
// --- Test helpers ---

// newTestInstallCmd builds the install command with the persistent --output flag
// the root command supplies in production, so root.OutputType does not panic when

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] "so root.OutputType does not panic" — install uses installOutputIsJSON, not root.OutputType; the persistent flag is actually needed so cobra can parse --output on a detached command. (Moot if the command switches to root.OutputType.)

@rclarey
rclarey force-pushed the aitools-install-output-json branch 2 times, most recently from 0f9f04a to af4bb2a Compare September 3, 2026 13:46
Add JSON output to `aitools install`, driven entirely by flags so the
run is fully non-interactive: require --scope and --agents (erroring and
naming the missing flags otherwise) so no scope prompt, agent picker, or
confirm is shown. executePlan now returns a per-agent outcome (name,
delivery, status, message) that the JSON payload lists. A top-level
failure with no per-agent entry (e.g. a skills-group install failure) is
surfaced in a top-level "error" field; per-agent failures stay in their
agent entry and are not duplicated there (executePlan wraps them so the
two are distinguishable). Once the JSON result is rendered, silence
cobra's text "Error:"/usage output so a failure is not reported twice;
the non-zero exit still comes from returning the run error. Share the
indented-JSON encoder between install and list as renderJSON.

Co-authored-by: Isaac <no-reply@databricks.com>
@rclarey
rclarey force-pushed the aitools-install-output-json branch from af4bb2a to 047ee54 Compare September 3, 2026 14:04
The changelog validator now requires each fragment to be a single line
starting with a `* ` bullet and ending with a period before the trailing
PR link group. Reformat the install --output json fragment accordingly.

Co-authored-by: Isaac <no-reply@databricks.com>
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: f05afd8

Run: 33884340398

Env 🔄​flaky 💚​RECOVERED ✅​pass 🙈​skip Time
💚​ aws linux 1 275 16 6:13
💚​ aws windows 1 277 14 4:40
💚​ azure linux 1 274 16 6:00
🔄​ azure windows 2 1 274 14 4:41
💚​ gcp linux 1 275 16 5:49
💚​ gcp windows 1 277 14 4:26
Test Name aws linux aws windows azure linux azure windows gcp linux gcp windows
💚​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🔄​ TestFsCpFileToFileFileNotOverwritten ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p
🔄​ TestFsCpFileToFileFileNotOverwritten/uc-volumes_to_uc-volumes ✅​p ✅​p ✅​p 🔄​f ✅​p ✅​p
Top 6 slowest tests (at least 2 minutes):
duration env testname
4:34 aws windows TestAccept
4:24 gcp windows TestAccept
4:17 azure windows TestAccept
3:56 aws linux TestAccept
3:49 azure linux TestAccept
3:45 gcp linux TestAccept

--output json is meant to emit only the structured JSON document, but the
installer still wrote progress lines ("Using skills version", "Fetching
skills manifest...", "Installed N skills.") to stderr, so a consumer saw
non-JSON interleaved with the result. Mark the context quiet in JSON mode
and route those library messages through cmdio.LogProgress, which respects
it. Text mode is unaffected. Update the acceptance test to use the
non-deprecated `aitools install` and assert only JSON is emitted.

Co-authored-by: Isaac <no-reply@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants